﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Timers;

namespace SpriteEditor
{
    public partial class frmMain
    {
        //Common updating
        public void refreshAnimationGrid()
        {
            dataGridView_Animations.DataSource = null;
            if (spr.lst_Animations != null && spr.lst_Animations.Count > 0)
                dataGridView_Animations.DataSource = spr.lst_Animations;
            dataGridView_Animations.Refresh();
        }

        public void refreshFrameOfAnimationsGrid()
        {
            dataGridView_FramesOfAnimation.DataSource = null;
            if (dataGridView_Animations.CurrentRow != null)
            {
                int curAnimation = dataGridView_Animations.CurrentRow.Index;
                if (spr.lst_Animations[curAnimation].lst_FramesOfAnimation != null
                    && spr.lst_Animations[curAnimation].lst_FramesOfAnimation.Count > 0)
                    dataGridView_FramesOfAnimation.DataSource = spr.lst_Animations[curAnimation].lst_FramesOfAnimation;
            }
            dataGridView_ModulesOfFrame.Refresh();
        }

        public void setCurrentAnimationOnGrid(int curIndex)
        {
            if (dataGridView_Animations.Rows.Count > curIndex)
            {
                dataGridView_Animations.ClearSelection();
                dataGridView_Animations.CurrentCell = dataGridView_Animations.Rows[curIndex].Cells[0];
                dataGridView_Animations.Rows[curIndex].Selected = true;
                updateCurAnimSelection();
                updateCurFOAnimsSelection();
            }
        }

        public void setCurrentFOAnimsOnGrid(int curIndex)
        {
            if (dataGridView_Animations.CurrentRow != null)
            {
                //int curAnim = dataGridView_Animations.CurrentRow.Index;
                if (dataGridView_FramesOfAnimation.Rows.Count > curIndex)
                {
                    dataGridView_FramesOfAnimation.ClearSelection();
                    dataGridView_FramesOfAnimation.CurrentCell = dataGridView_FramesOfAnimation.Rows[curIndex].Cells[0];
                    dataGridView_FramesOfAnimation.Rows[curIndex].Selected = true;
                    updateCurFOAnimsSelection();
                }
            }
        }

        private void updateCurAnimSelection()
        {
            if (dataGridView_Animations.DataSource != null && dataGridView_Animations.CurrentRow != null
                    && spr != null && spr.lst_Animations != null
                    && dataGridView_Animations.CurrentRow.Index < spr.lst_Animations.Count)
            {
                dataGridView_FramesOfAnimation.DataSource = null;
                if (spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation != null
                    && spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation.Count > 0)
                    dataGridView_FramesOfAnimation.DataSource = spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation;
            }
        }

        private void updateCurFOAnimsSelection()
        {
            if (dataGridView_Animations != null && dataGridView_Animations.DataSource != null
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_FramesOfAnimation != null && dataGridView_FramesOfAnimation.DataSource != null
                && dataGridView_FramesOfAnimation.CurrentRow != null
                && spr.lst_Animations != null
                && spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation != null)
            {
                int cur_AnimationIndex = dataGridView_Animations.CurrentRow.Index;

                int cur_FrameOfAnimationIndex = dataGridView_FramesOfAnimation.CurrentRow.Index;

                int cur_FrameIndex = -1;
                if (spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation.Count <= 0)
                {
                    CurSel_Animation = null;
                    CurSel_Animation = new AnimationSelection();
                    return;
                }

                if (
                    cur_FrameOfAnimationIndex >= 0
                    && spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation.Count > 0
                    && cur_FrameOfAnimationIndex < spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation.Count
                    )
                {
                    cur_FrameIndex = spr.getFrameIndexFromID(spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation[cur_FrameOfAnimationIndex].ID);
                }
                else
                {
                    cur_FrameIndex = -1;
                }
                if (cur_FrameOfAnimationIndex >= 0 && cur_FrameIndex >= 0)
                {
                    if (CurSel_Animation == null)
                        CurSel_Animation = new AnimationSelection();
                    CurSel_Animation.CurrentAnimationIndex = cur_AnimationIndex;
                    CurSel_Animation.CurrentFrameOfAnimationIndex = cur_FrameOfAnimationIndex;
                    CurSel_Animation.CurrentFrameIndex = cur_FrameIndex;
                    CurSel_Animation.P1 = new Point(spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation[cur_FrameOfAnimationIndex].OX + spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation[cur_FrameOfAnimationIndex].getFramFromId().X,
                                                spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation[cur_FrameOfAnimationIndex].OY + spr.lst_Animations[cur_AnimationIndex].lst_FramesOfAnimation[cur_FrameOfAnimationIndex].getFramFromId().Y );
                    CurSel_Animation.P2 = new Point(CurSel_Animation.P1.X + spr.lst_Frames[cur_FrameIndex].W,
                                                CurSel_Animation.P1.Y + spr.lst_Frames[cur_FrameIndex].H);
                }
                else
                {
                    CurSel_Animation = null;
                }
                DrawPanelAnimation();
            }
            else
            {
                CurSel_Animation = null;
            }
        }

        public void updateFOAminssGridFromCurSel_Anim()
        {
            bAnimationUpdateSelection = false;
            if (CurSel_Animation != null && spr.lst_Animations != null
                && spr.lst_Animations.Count > CurSel_Animation.CurrentAnimationIndex
                && spr.lst_Animations[CurSel_Animation.CurrentAnimationIndex].lst_FramesOfAnimation != null)
            {
                dataGridView_FramesOfAnimation.CurrentCell = dataGridView_FramesOfAnimation.Rows[CurSel_Animation.CurrentFrameOfAnimationIndex].Cells[0];
                dataGridView_FramesOfAnimation.Rows[CurSel_Animation.CurrentFrameOfAnimationIndex].Selected = true;
            }

            dataGridView_FramesOfAnimation.Refresh();
        }

        //New Animation button click
        public void newAnimation()
        {
            if (spr != null && spr.spr_image != null && spr.lst_Modules != null && spr.lst_Frames != null)
            {
                spr.newAnimation();

                refreshAnimationGrid();
                setCurrentAnimationOnGrid(dataGridView_Animations.Rows.Count - 1);
                DrawPanelAnimation();
            }
        }

        //Delete Animation button click
        public void deleteAnimation()
        {
            if (dataGridView_Animations.DataSource != null
                && dataGridView_Animations.CurrentRow != null
                && spr != null && spr.lst_Animations != null
                && dataGridView_Animations.Rows.Count > 0
                )
            {
                spr.removeAnimationAtIndex(dataGridView_Animations.CurrentRow.Index);

                refreshAnimationGrid();
                DrawPanelAnimation();
            }
        }

        //Clone Animation button click
        public void cloneAnimation()
        {
            if (spr != null && spr.lst_Animations != null
                && dataGridView_Animations.DataSource != null
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count > 0)
            {
                int currentIdex = dataGridView_Animations.CurrentRow.Index;
                spr.cloneAnimationAtIndex(currentIdex);

                refreshAnimationGrid();
                setCurrentAnimationOnGrid(currentIdex + 1);
                DrawPanelAnimation();
            }
        }

        //Up Animation button click
        public void upAnimation()
        {
            if (spr != null && spr.lst_Animations != null && spr.lst_Animations.Count >= 2
                && dataGridView_Animations.DataSource != null
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count >= 2)
            {
                int currentRow = dataGridView_Animations.CurrentRow.Index;
                if (currentRow > 0)
                {
                    spr.upAnimationAtIndex(currentRow);

                    refreshAnimationGrid();
                    setCurrentAnimationOnGrid(currentRow - 1);
                    DrawPanelAnimation();
                }
            }
        }

        //Down Animation button click
        public void downAnimation()
        {
            if (spr != null && spr.lst_Animations != null && spr.lst_Animations.Count >= 2
                && dataGridView_Animations.DataSource != null
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count >= 2)
            {
                int currentRow = dataGridView_Animations.CurrentRow.Index;
                if (currentRow < dataGridView_Animations.Rows.Count - 1)
                {
                    spr.downAnimationAtIndex(currentRow);

                    refreshAnimationGrid();
                    setCurrentAnimationOnGrid(currentRow + 1);
                    DrawPanelAnimation();
                }
            }
        }

        //New Frame Of Animation button click
        public void newFrameOfAnim()
        {
            if (spr != null && spr.spr_image != null && spr.lst_Modules != null && spr.lst_Frames != null
                && dataGridView_Animations.CurrentRow != null)
            {
                int currentAnim = dataGridView_Animations.CurrentRow.Index;

                spr.newFrameOfAnimations(currentAnim, curFrameIndexInAnimFlow);

                refreshFrameOfAnimationsGrid();
                setCurrentFOAnimsOnGrid(dataGridView_FramesOfAnimation.Rows.Count - 1);
                DrawPanelAnimation();
            }
        }

        //Delete Frame Of Animation button click
        public void deleteFrameOfAnim()
        {
            if (dataGridView_Animations.DataSource != null && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count > 0
                && dataGridView_FramesOfAnimation.DataSource != null && dataGridView_FramesOfAnimation.CurrentRow != null
                && dataGridView_FramesOfAnimation.Rows.Count > 0
                && spr != null && spr.lst_Animations != null
                && spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation != null
                && spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation.Count > 0)
            {
                int crt_AnimIndex = dataGridView_Animations.CurrentRow.Index;
                int crt_FOAIndex = dataGridView_FramesOfAnimation.CurrentRow.Index;

                spr.deleteFrameOfAnimations(crt_AnimIndex, crt_FOAIndex);

                refreshFrameOfAnimationsGrid();
                DrawPanelAnimation();
            }
        }

        //Clone Frame Of Animation button click
        public void cloneFrameOfAnim()
        {
            if (spr != null && spr.lst_Animations != null && spr.lst_Animations.Count > 0
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count > 0)
            {
                int crt_AnimIndex = dataGridView_Animations.CurrentRow.Index;
                if (spr.lst_Animations[crt_AnimIndex].lst_FramesOfAnimation != null
                    && spr.lst_Animations[crt_AnimIndex].lst_FramesOfAnimation.Count > 0
                    && dataGridView_FramesOfAnimation.CurrentRow != null
                    && dataGridView_FramesOfAnimation.Rows.Count > 0)
                {
                    int crt_FOAIndex = dataGridView_FramesOfAnimation.CurrentRow.Index;

                    spr.cloneFrameOfAnimations(crt_AnimIndex, crt_FOAIndex);


                    refreshFrameOfAnimationsGrid();
                    setCurrentFOAnimsOnGrid(crt_FOAIndex + 1);
                    DrawPanelAnimation();
                }
            }
        }

        //Up Frame Of Animation button click
        public void upFrameOfAnim()
        {
            if (spr != null && spr.lst_Animations != null && spr.lst_Animations.Count > 0
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count > 0)
            {
                int crt_AminIndex = dataGridView_Animations.CurrentRow.Index;
                if (spr.lst_Animations[crt_AminIndex].lst_FramesOfAnimation != null
                    && spr.lst_Animations[crt_AminIndex].lst_FramesOfAnimation.Count >= 2
                    && dataGridView_FramesOfAnimation.CurrentRow != null
                    && dataGridView_FramesOfAnimation.Rows.Count >= 2)
                {
                    int crt_FOAmins = dataGridView_FramesOfAnimation.CurrentRow.Index;
                    if (crt_FOAmins > 0)
                    {
                        spr.upFrameOfAnimationsAtIndex(crt_AminIndex, crt_FOAmins);

                        refreshFrameOfAnimationsGrid();
                        setCurrentFOAnimsOnGrid(crt_FOAmins - 1);
                        DrawPanelAnimation();
                    }
                }
            }
        }

        //Down Frame Of Animation button click
        public void downFrameOfAnim()
        {
            if (spr != null && spr.lst_Animations != null && spr.lst_Animations.Count > 0
                && dataGridView_Animations.CurrentRow != null
                && dataGridView_Animations.Rows.Count > 0)
            {
                int crt_AminIndex = dataGridView_Animations.CurrentRow.Index;
                if (spr.lst_Animations[crt_AminIndex].lst_FramesOfAnimation != null
                    && spr.lst_Animations[crt_AminIndex].lst_FramesOfAnimation.Count >= 2
                    && dataGridView_FramesOfAnimation.CurrentRow != null
                    && dataGridView_FramesOfAnimation.Rows.Count >= 2)
                {
                    int crt_FOAmins = dataGridView_FramesOfAnimation.CurrentRow.Index;
                    if (crt_FOAmins < dataGridView_FramesOfAnimation.Rows.Count - 1)
                    {
                        spr.downFrameOfAnimationsAtIndex(crt_AminIndex, crt_FOAmins);

                        refreshFrameOfAnimationsGrid();
                        setCurrentFOAnimsOnGrid(crt_FOAmins + 1);
                        DrawPanelAnimation();
                    }
                }
            }
        }

        //Draw Panel Animation
        private void DrawPanelAnimation()
        {
            if (bufferBitmap == null || panel_Animations.Width != bufferBitmap.Width || panel_Animations.Height != bufferBitmap.Height)
            {
                if (panel_Animations.Width > 0 && panel_Animations.Height > 0)
                    bufferBitmap = new Bitmap(panel_Animations.Width, panel_Animations.Height);
            }
            Graphics g_main = panel_Animations.CreateGraphics();
            Graphics g = Graphics.FromImage(bufferBitmap);
            g.Clear(panel_Animations.BackColor);

            if (spr != null && spr.spr_image != null)
            {
                Pen root_pen = new Pen(Color.Brown, 2);
                g.DrawLine(root_pen, new Point(0, root_Animations_Grid_Pos.Y), new Point(panel_Animations.Width, root_Animations_Grid_Pos.Y));
                g.DrawLine(root_pen, new Point(root_Animations_Grid_Pos.X, 0), new Point(root_Animations_Grid_Pos.X, panel_Animations.Height));

                if (spr.lst_Animations != null)
                {
                    if (spr.lst_Animations != null
                        && spr.lst_Animations.Count > 0
                        && dataGridView_Animations.CurrentRow.Index < spr.lst_Animations.Count
                        && spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation != null
                        && spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation.Count > 0)
                    {
                        List<FramesOfAnimation> tmp_lst_foam = spr.lst_Animations[dataGridView_Animations.CurrentRow.Index].lst_FramesOfAnimation;
                        int cur_indexFOA = dataGridView_FramesOfAnimation.CurrentRow.Index;
                        if (cur_indexFOA >= tmp_lst_foam.Count)
                            cur_indexFOA = tmp_lst_foam.Count - 1;
                        Frame tmp_Frame = spr.getFrameFromID(tmp_lst_foam[cur_indexFOA].ID);
                        if (tmp_Frame == null || tmp_Frame.img == null)
                        {
                            g.DrawString("Invalid Frame", new Font(new FontFamily("Arial"), 12), new SolidBrush(Color.Red), new Point(10, 10));
                        }
                        else
                        {
                            Point tmp_module_pos = SpriteCalculation.ConvertToRoot(new Point(tmp_lst_foam[cur_indexFOA].OX + tmp_Frame.X, tmp_lst_foam[cur_indexFOA].OY + tmp_Frame.Y), root_Animations_Grid_Pos);
                            g.DrawImage(tmp_Frame.img, tmp_module_pos);
                        }
                    }
                }
            }
            g_main.DrawImage(bufferBitmap, 0, 0);
        }

        private void DrawFlowPanelAnimation()
        {
            flowLayoutPanel_Animation.Controls.Clear();

            if (spr != null && spr.spr_image != null && spr.lst_Frames != null)
            {
                for (int i = 0; i < spr.lst_Frames.Count; i++)
                {
                    OwnPanel frames_flow_panel = new OwnPanel() { Width = 94, Height = 94 };
                    frames_flow_panel.BorderStyle = BorderStyle.Fixed3D;

                    if (spr.lst_Frames[i].img != null)
                    {
                        int f_tile = SpriteCalculation.Min(92000 / spr.lst_Frames[i].img.Width, 92000 / spr.lst_Frames[i].img.Height);

                        Bitmap small_bitmap = new Bitmap(spr.lst_Frames[i].img, spr.lst_Frames[i].img.Width * f_tile / 1000, spr.lst_Frames[i].img.Height * f_tile / 1000);

                        frames_flow_panel.BackgroundImage = small_bitmap;
                    }
                    else
                    {
                        frames_flow_panel.BackColor = EMPTY_CONTROL_COLOR;
                    }
                    frames_flow_panel.BackgroundImageLayout = ImageLayout.Center;
                    if (i == curFrameIndexInAnimFlow)
                        frames_flow_panel.BackColor = CURRENT_SELECTION_COLOR;
                    //else
                    //    frames_flow_panel.BackColor = Color.LightGray;

                    frames_flow_panel.CurrentIndex = i;
                    frames_flow_panel.MouseDoubleClick += new MouseEventHandler(frames_flow_panel_MouseDoubleClick);
                    frames_flow_panel.MouseClick += new MouseEventHandler(frames_flow_panel_MouseClick);

                    flowLayoutPanel_Animation.Controls.Add(frames_flow_panel);
                }
            }
        }

        public void updateFlowPanelAnimationSelection(int curFOASelection)
        {
            if (flowLayoutPanel_Animation.Controls != null
                && flowLayoutPanel_Animation.Controls.Count > 0
                && curFOASelection >= 0
                && flowLayoutPanel_Animation.Controls.Count > curFOASelection)
            {
                curFrameIndexInAnimFlow  = curFOASelection;
                for (int i = 0; i < flowLayoutPanel_Animation.Controls.Count; i++)
                {
                    if (i == curFrameIndexInAnimFlow)
                        flowLayoutPanel_Animation.Controls[i].BackColor = CURRENT_SELECTION_COLOR;
                    else
                        flowLayoutPanel_Animation.Controls[i].BackColor = Color.LightGray;
                }
                //flowLayoutPanel_Frame.Refresh();
            }
        }

        //Playing animation
        private List<int> getAnimQueue()
        {
            int cur_IndexAnim = dataGridView_Animations.CurrentRow.Index;
            int total_FsOA = dataGridView_FramesOfAnimation.Rows.Count;

            if (spr == null || spr.lst_Animations == null
                || spr.lst_Animations[cur_IndexAnim].lst_FramesOfAnimation == null)
                return null;
            if (total_FsOA <= 0 || cur_IndexAnim >= spr.lst_Animations.Count)
                return null;

            anim_queue = new List<int>();
            for (int i = 0; i < total_FsOA; i++)
            {
                FramesOfAnimation tmp_anim = spr.lst_Animations[cur_IndexAnim].lst_FramesOfAnimation[i];
                for (int j = 0; j < tmp_anim.Time; j++)
                {
                    anim_queue.Add(i);
                }
            }
            return anim_queue;
        }

        private void PlayAnim()
        {
            is_PlayingAnim = true;
            button_PlayAnim.Text = "Stop";
            Anim_timer.Interval = 1000 / Convert.ToInt32(numericUpDown_FPS.Value);
            anim_queue = getAnimQueue();
            anim_idx = 0;
            Anim_timer.Start();
        }

        private void StopAnim()
        {
            is_PlayingAnim = false;
            button_PlayAnim.Text = "Play";
            Anim_timer.Stop();
        }
    }
}